import { fabric } from 'fabric';
var TextboxWithPadding = fabric.util.createClass(fabric.Textbox, {
  _renderBackground: function (ctx) {
    if (!this.backgroundColor) {
      return;
    }
    var dim = this._getNonTransformedDimensions();
    ctx.fillStyle = this.backgroundColor;

    ctx.fillRect(
      -dim.x / 2 - this.padding,
      -dim.y / 2 - this.padding,
      dim.x + this.padding * 2,
      dim.y + this.padding * 2
    );
    // if there is background color no other shadows
    // should be casted
    this._removeShadow(ctx);
  }
});

import PubSub from "pubsub-js"
import { INITIALIZED, UPDATE_ITEM, ADD_ITEM, CHANGE_YTPE, CHANGE_ACTIVE, SET_TITLE } from './event-types';

import colorParse from 'color-parse';


export const ACTION_TYPES = {
  rect: 0,
  multiple: 1,
  move: 2,
};
export default {
  isDraw: false,
  noMove: 0,
  type: 0,
  currentDrawObj: null,
  labelList: [],
  currentHandleImg: null,
  content: null,
  startPoint: {
    x: 0,
    y: 0
  },
  point: null,
  callback: null,
  updateCallback: null,
  onChangeType: null,
  addCallback: null,
  onChangeActive: null,
  followObj: null,
  followstat: 0,//'左击进行绘制，右击取消绘制状态', // 左击进行绘制，右击取消本次绘制
  unfollow () {
    this.followObj && this.content.remove(this.followObj);
  },
  follow ({ x, y }) {
    this.unfollow();
    const zoom = this.content.getZoom();
    const r = 12 / 2 / zoom;
    const sw = 2 / zoom;
    const current = new fabric.Circle({
      top: y - r - sw / 2,
      left: x - r - sw / 2,
      radius: r,
      fill: '#669ce1',
      strokeWidth: sw,
      stroke: '#ffffff',
    });
    const tb = new fabric.IText(this.isDraw ? '左击进行绘制，右击取消本次绘制' : '左击进行绘制，右击取消绘制状态', {
      selected: false,
      selectable: false,
      top: y - r - sw - 12 / zoom - 5,
      left: x + r,
      fontSize: 12 / zoom,
      fill: '#fff',
      backgroundColor: 'rgba(0,0,0,0.4)',
      textBackgroundColor: 'rgba(0,0,0,0.4)',
    });

    const follow_g = new fabric.Group([current, tb], {
      selectable: false
    });
    this.content.add(follow_g);

    this.followObj = follow_g;
  },
  // 监听update
  onUpdate () {
    // this.updateCallback = fn1;
    // this.addCallback = fn2;
    // this.onChangeType = fn3;
    // this.onChangeActive = fn4;
  },
  // 今天设置文字
  onSetTitleCallBack (fn) {
    this.callback = fn;
  },
  // 移除当前
  removeCurrentObj () {
    this.currentDrawObj && this.content.remove(this.currentDrawObj);
    this.currentDrawObj = null;
  },
  // 触发
  onSetTitle ({ name, color } = {}) {
    const rectBox = this.drawEnd(this.point[0], this.point[1], color);
    this.content.add(rectBox);
    const coordinates = this.getCoordinates(rectBox);
    rectBox._name = name;
    rectBox._code = color;
    this.labelList.push({
      text: name,
      label: rectBox,
      color: color,
      coordinates
    });
    this.currentDrawObj = null;
    // 更新
    const msg = {
      name,
      color: color,
      property: coordinates,
    };
    PubSub.publish(ADD_ITEM, msg);
    // this.addCallback && this.addCallback();
    this.loadTitle();
  },
  selectedActive () {
    const currentActive = this.content.getActiveObject();
    // this.onChangeActive(currentActive && currentActive._id || '');
    PubSub.publish(CHANGE_ACTIVE, currentActive && currentActive._id || '');
  },
  // 初始化
  initCanvas (canvasId) {
    const content = this.content = new fabric.Canvas(canvasId, {
      uniScaleTransform: true // 拉伸不固定比例
    });
    fabric.Object.prototype.transparentCorners = false;
    fabric.Object.prototype.hasRotatingPoint = false;
    fabric.Object.prototype.borderColor = '#ff0000';
    fabric.Object.prototype.strokeWidth = 2;
    fabric.Object.prototype.cornerColor = '#ff0000';
    fabric.Object.prototype.cornerStrokeColor = '#ff0000';
    fabric.Object.prototype.cornerStyle = 'circle';

    // ['tl', 'tr', 'bl', 'br'].forEach(item => {
    //   fabric.Object.prototype.setControlVisible(item, false);
    // })

    content.skipTargetFind = true; //画板元素不能被选中
    content.selection = false; //画板不显示选中
    let panning = false;

    // 鼠标按下
    content.on('mouse:down', options => {
      // console.log('mouse:down', options);

      if (this.type === 0) {
        if (this.isDraw) {
          return;
        }
        this.noMove = 0;
        const { x, y } = options.absolutePointer;
        this.startPoint.x = x;
        this.startPoint.y = y;
      } else if (this.type === 1) {
        // TODO 多边形 
      } else if (this.type === 2) {
        // TODO 可移动的
        panning = true;
        this.selectedActive();
      }

    });

    //鼠标抬起
    content.on('mouse:up', (options) => {

      if (this.type === 0) {
        const startPoint = { ...this.startPoint };
        // console.log(options);
        const endPoint = { ...options.absolutePointer };
        const isDraw = this.isDraw;
        if (this.noMove < 3) {
          this.isDraw = true;
          this.noMove = 0;
        } else {
          this.isDraw = false;
        }
        // 判断上一次的值，真说明已经画完了
        if (isDraw) {
          console.log('这里弹出框，选择类型');
          // 计算一下 startPoint 和 endPoint

          const iw = this.iw;
          const ih = this.ih;

          // console.log('startPoint', JSON.stringify(startPoint));
          // console.log('endPoint', JSON.stringify(endPoint));


          let lx = Math.min(endPoint.x, startPoint.x);
          let ly = Math.min(endPoint.y, startPoint.y);

          let rx = Math.max(endPoint.x, startPoint.x);
          let ry = Math.max(endPoint.y, startPoint.y);

          startPoint.x = Math.max(lx, 0);
          startPoint.y = Math.max(ly, 0);

          endPoint.x = Math.min(iw, rx);
          endPoint.y = Math.min(ih, ry);

          if (this.validation(startPoint) && this.validation(endPoint)) {
            this.point = [startPoint, endPoint];
            // this.callback && this.callback();
            PubSub.publish(SET_TITLE);
          } else {
            this.removeCurrentObj();
          }
        }
        this.drawLine(options.absolutePointer);
        this.follow(options.absolutePointer);
      } else if (this.type === 1) {
        // TODO 多边形 
      } else if (this.type === 2) {
        // TODO 可移动的
        panning = false;
      }

    });

    //鼠标移动
    content.on('mouse:move', options => {
      if (this.type === 0) {
        this.draw(options.absolutePointer);
        this.drawLine(options.absolutePointer);
        this.follow(options.absolutePointer);
        this.noMove += 1;
      } else if (this.type === 1) {
        // TODO 多边形 
      } else if (this.type === 2) {
        // TODO 可移动的
        if (panning) {
          if (!options.target || !options.target.selectable) {
            const delta = new fabric.Point(options.e.movementX, options.e.movementY);
            content.relativePan(delta);
          }
        }
      }

    });

    content.on('object:scaling', (e) => {

      const o = e.target;
      if (!o.strokeWidthUnscaled && o.strokeWidth) {
        o.strokeWidthUnscaled = o.strokeWidth;
      }
      if (o.strokeWidthUnscaled) {
        o.strokeWidth = o.strokeWidthUnscaled / Math.max(o.scaleX, o.scaleY);
      }
    });

    content.on('object:modified', (e) => {
      const startPoint = {
        x: Math.max(e.target.left, 0),
        y: Math.max(e.target.top, 0)
      };
      const endPoint = {};
      let w = e.target.width;
      let h = e.target.height;
      // console.log(e.transform.action);

      if ("scale" === e.transform.action) {

        console.log("OLD SCALE: " + e.transform.original.scaleX);
        console.log("NEW SCALE: " + e.transform.newScaleX);
        console.log("OLD WIDTH: " + (e.target.width * e.transform.scaleX));
        console.log("NEW WIDTH: " + (e.target.width * e.transform.newScaleX));
        console.log("OLD HEIGHT: " + (e.target.height * e.transform.scaleY));
        console.log("NEW HEIGHT: " + (e.target.height * e.transform.newScaleY));
        w = (e.target.width * e.transform.newScaleX);
        h = (e.target.height * e.transform.newScaleY);
      }
      else if ("scaleX" === e.transform.action) {
        console.log("OLD SCALE: " + e.transform.original.scaleX);
        console.log("NEW SCALE: " + e.transform.newScaleX);
        console.log("OLD WIDTH: " + (e.target.width * e.transform.scaleX));
        console.log("NEW WIDTH: " + (e.target.width * e.transform.newScaleX));
        w = (e.target.width * e.transform.newScaleX);
        h = e.target.height;
      }
      else if ("scaleY" === e.transform.action) {
        console.log("OLD SCALE: " + e.transform.original.scaleY);
        console.log("NEW SCALE: " + e.transform.newScaleY);
        console.log("OLD HEIGHT: " + (e.target.height * e.transform.scaleY));
        console.log("NEW HEIGHT: " + (e.target.height * e.transform.newScaleY));
        w = e.target.width;
        h = (e.target.height * e.transform.newScaleY);
      }

      endPoint['x'] = Math.min(w + startPoint['x'], this.iw);
      endPoint['y'] = Math.min(h + startPoint['y'], this.ih);

      if (e.target && e.target.type === 'rect') {
        // console.log('startPoint, endPoint===>  ', JSON.stringify(startPoint), JSON.stringify(endPoint));

        const rectBox = this.drawEnd(startPoint, endPoint);
        const currentLabel = this.labelList.find(label => {
          return label.id === e.target._id;
        });
        if (!currentLabel) return;
        rectBox._id = currentLabel.id;
        rectBox._name = currentLabel.name;
        rectBox._color = currentLabel.color;
        currentLabel.label = rectBox;
        this.content.remove(e.target);
        this.content.add(rectBox);

        const coordinates = this.getCoordinates(rectBox);
        if (e.target._id) {
          const msg = {
            id: e.target._id,
            name: e.target._name,
            color: e.target._color,
            property: coordinates,
          };
          PubSub.publish(UPDATE_ITEM, msg);
          // this.updateCallback && this.updateCallback();
        }
        this.loadTitle();
      }
    });

    // content.on('object:actied', (e) => {
    //   console.log('selected', e);
    // });
  },
  unDrawLine () {
    this.content.remove(this.line_g)
  },
  drawLine ({ x, y }) {
    this.unDrawLine();
    // this.line_g && this.line_g.destroy();
    // if (this.line_g) {
    //   console.log('this.line_g', this.line_g);
    //   const [lx, ly] = this.line_g._objects;
    //   lx.set('x1', x - 10000)
    //   lx.set('x2', x + 10000)
    //   ly.set('y1', y - 10000)
    //   ly.set('y2', y + 10000)
    //   console.log();

    //   return;
    // }
    const zoom = this.content.getZoom();
    const sw = 2 / zoom;
    x -= sw;
    y -= sw;

    const linex = new fabric.Line([x - 10000, y, x + 10000, y], {
      stroke: '#fff',//笔触颜色
      strokeWidth: sw,
      objectCaching: false,
    });
    const liney = new fabric.Line([x, y - 10000, x, y + 10000], {
      stroke: '#fff',//笔触颜色
      strokeWidth: sw,
      objectCaching: false,
    });

    const line_g = new fabric.Group([linex, liney], {
      objectCaching: false,
      selectable: false,
      // strokeWidth: sw
    });
    this.line_g = line_g;
    this.content.add(line_g);
  },
  onRightClick () {
    if (this.type === 0) {
      // 矩形
      if (this.isDraw) {
        this.isDraw = false;
        this.removeCurrentObj();

        this.followObj && this.followObj._objects[1].set('text', '左击进行绘制，右击取消绘制状态')
      } else {
        this.setType(2);
      }
    } else if (this.type === 1) {
      // TODO 多边形 
    } else if (this.type === 2) {
      // TODO 可移动的
    }
  },
  // 加载标题
  loadTitle () {
    const content = this.content;

    this.labelList.forEach((item) => {
      // console.log('item',item)
      const { text, label, color } = item;

      item.textbox && content.remove(item.textbox);

      const point = {
        x: label.left,
        y: label.top,
      };

      const _drawTitle = this.drawTitle(point, text, color);

      content.add(_drawTitle)
      item.textbox = _drawTitle;
    });
  },
  // 初始化图片，标签
  initData (image, pointlist = []) {
    console.log('image', image);

    this.content && this.content.clear();
    fabric.Image.fromURL(image, (image) => {
      console.log('initImage,', image);

      this.currentHandleImg = image;
      this.iw = image.width;
      this.ih = image.height;
      image.set('selectable', false);
      this.content.insertAt(image);
      this.zoomToFitCanvas();
      this.showLabel(pointlist);
      PubSub.publish(INITIALIZED);
    });
  },
  showLabel (pointlist = []) {
    console.log('pointlist', pointlist)
    const labelList = this.labelList;
    this.labelList = [];
    labelList.forEach(label => {
      label.label && this.content.remove(label.label);
      label.textbox && this.content.remove(label.textbox);
    });
    if (Array.isArray(pointlist)) {
      console.log('pointlist', pointlist);

      // point [[x,y],[x,y],[x,y],[x,y]]
      let content = this.content;
      pointlist.forEach(label => {
        const point = label.property;
        // 起点        
        const startLT = point[0];
        const startRB = point[2];
        const startPoint = {
          x: startLT[0],
          y: startLT[1],
        };
        const endPoint = {
          x: startRB[0],
          y: startRB[1],
        };
        // const textBox = this.drawTitle(startPoint, label.name);
        const rectBox = this.drawEnd(startPoint, endPoint, label.color);
        const coordinates = this.getCoordinates(rectBox);

        // const group = new fabric.Group([rectBox, textBox]);
        content.add(rectBox);
        rectBox._name = label.name;
        rectBox._color = label.color;
        rectBox._id = label.id;
        this.labelList.push({
          id: label.id,
          text: label.name,
          label: rectBox,
          color: label.color,
          coordinates
        });
      });
      this.loadTitle();
    }
  },
  // 设置当前类型
  setType (type) {
    this.type = type;
    // this.onChangeType && this.onChangeType(type);
    PubSub.publish(CHANGE_YTPE, type);
    if (this.type === 2) {
      this.content.selection = false;
      this.content.selectable = false;
      this.content.skipTargetFind = false;
      this.unfollow();
      this.unDrawLine();
    } else {
      this.content.selectable = false;
      this.content.selection = false;
      this.content.skipTargetFind = true;
    }
  },
  // 缩放
  zoomToPoint ({ pageX = 0, pageY = 0, deltaY, zoom_size = 0.02 }, d_zoom) {

    let zoom = (deltaY < 0 ? zoom_size : -zoom_size) + this.content.getZoom();
    zoom = Math.max(0.1, zoom); // 最小为原来的1/10
    zoom = Math.min(2, zoom); // 最大是原来的3倍
    const zoomPoint = new fabric.Point(pageX, pageY);
    this.content.zoomToPoint(zoomPoint, d_zoom || zoom);
    // if(this.type != 2){
    //   this.follow(zoomPoint);
    // }
    this.unfollow();
    this.loadTitle();
    this.unDrawLine();
  },
  // 缩放
  zoomToFitCanvas () {
    //先还原缩放比例与位置
    const content = this.content;
    content.setZoom(1);
    content.absolutePan({ x: 0, y: 0 });
    //遍历所有对对象，获取最小坐标，最大坐标
    var objects = content.getObjects();
    if (objects.length > 0) {
      var rect = objects[0].getBoundingRect();
      var minX = rect.left;
      var minY = rect.top;
      var maxX = rect.left + rect.width;
      var maxY = rect.top + rect.height;
      for (var i = 1; i < objects.length; i++) {
        rect = objects[i].getBoundingRect();
        minX = Math.min(minX, rect.left);
        minY = Math.min(minY, rect.top);
        maxX = Math.max(maxX, rect.left + rect.width);
        maxY = Math.max(maxY, rect.top + rect.height);
      }
    }

    //计算平移坐标
    var panX = (maxX - minX - content.width) / 2 + minX;
    var panY = (maxY - minY - content.height) / 2 + minY;
    //开始平移
    content.absolutePan({ x: panX, y: panY });

    //计算缩放比例
    var zoom = Math.min(content.width / (maxX - minX), content.height / (maxY - minY));
    //计算缩放中心
    var zoomPoint = new fabric.Point(content.width / 2, content.height / 2);
    //开始缩放
    content.zoomToPoint(zoomPoint, zoom * 0.92);

  },
  // 显示矩形
  drawEnd (startPoint, endPoint, color) {
    const pColor = colorParse(color || '#ffffff');
    pColor.values.push('0.5');
    console.log('pColor', pColor);
    let currentDrawObj = this.currentDrawObj;
    let content = this.content;
    // 清空当前的
    if (currentDrawObj !== null) {
      content.remove(currentDrawObj);
    }
    let { x, y } = endPoint;

    let lx = Math.min(x, startPoint.x);
    let ly = Math.min(y, startPoint.y);
    currentDrawObj = new fabric.Rect({
      left: lx,
      top: ly,
      fill: color ? `rgba(${pColor.values.join(',')})` : 'rgba(0,0,0,0.3)',
      hasRotatingPoint: false,
      width: Math.abs(x - startPoint.x),
      height: Math.abs(y - startPoint.y)
    });
    // console.log('===>   ', x, y, lx, ly, currentdrawobj);

    currentDrawObj.set({ strokeWidth: 3, stroke: color || '#669ce1' });
    return currentDrawObj;
  },
  // 画
  draw (endPoint) {
    if (!this.isDraw) return;
    let startPoint = this.startPoint;
    const currentDrawObj = this.currentDrawObj = this.drawEnd(startPoint, endPoint);

    this.content.add(currentDrawObj);
  },
  // 画标题
  drawTitle (point, text, color) {
    const pColor = colorParse(color || '#ffffff');
    // pColor.values.push(0);
    // console.log('size', 26 / this.content.getZoom(), this.content.getZoom());
    const size = 12 / this.content.getZoom();

    const padding = 4;
    const titleBox = new TextboxWithPadding(text, {
      padding: padding,
      fontFamily: 'Comic Sans',
      left: point.x - 0.5 + padding,
      top: point.y - (size + 1) - padding,
      fontSize: size,
      backgroundColor: color ? color : '#669ce1',
      // textBackgroundColor: color ? `rgba(${pColor.values.join(',')})` : '#669ce1',
      fill: '#ffffff',
    });
    titleBox.set('selectable', false);
    return titleBox;
  },
  // 验证矩形点
  validation ({ x, y }) {

    const iw = this.iw;
    const ih = this.ih;

    if (x >= 0 && x <= iw) {
      if (y >= 0 && y <= ih) {
        return true;
      }
    }
    return false;

  },
  // 从左上到左下 顺时针四个点
  getCoordinates (klass) {
    const ltx = Math.round(klass.left);
    const lty = Math.round(klass.top);
    const rbx = Math.round(ltx + klass.width);
    const rby = Math.round(lty + klass.height);

    const coordinates = [
      [ltx, lty],
      [rbx, lty],
      [rbx, rby],
      [ltx, rby]
    ];

    return coordinates;
  },
  getSelectObject (event) {
    var objects = this.content.getObjects();
    for (var i = objects.length - 1; i >= 0; i--) {
      var object = objects[i];
      //判断该对象是否在鼠标点击处
      if (this.content.containsPoint(event, object)) {
        if (object.type === 'rect') {
          // console.log(object);
          //选中该对象
          // this.content.setActiveObject(object);
          return object._id;
        }
      }
    }
    return null;
  },
  selectObject (id) {
    const currentLabel = this.labelList.find(item => {
      return item.id == id;
    });
    // console.log(currentLabel.label);
    currentLabel && this.content.setActiveObject(currentLabel.label);
    this.content.requestRenderAll();
    this.selectedActive();
  },
}